package indi.kider.sys.gateway.authc;

import com.google.common.base.Strings;
import com.google.gson.Gson;
import indi.kider.common.model.authc.User;
import indi.kider.common.model.employee.Employee;
import indi.kider.common.util.AuthcUtil;
import indi.kider.sys.gateway.related.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import pers.vankid.common.constant.HttpCode;
import pers.vankid.common.model.base.CommonResponse;
import pers.vankid.common.utils.redis.RedisUtil;
import pers.vankid.common.utils.tomcat.IPUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * Created by shixj on 2018/4/24.
 */
@Component
@Slf4j
public class AuthcManager {
    private static final String RENT = "rent";
    private static final String ID = "id";
    private static final String JSON = "json";

    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private RedisUtil redisUtil;

    /**
     * 验证登录
     *
     * @param userPermission
     * @return
     */
    public CommonResponse submitLogin(Employee userPermission, HttpServletRequest request) {
        CommonResponse commonResponse = new CommonResponse();
        commonResponse.setData("");
        String pwd = userPermission.getPwd();
        CommonResponse<List<Employee>> userResponse = null;
        try {
            if (userPermission != null && userPermission.getLoginName() != null)
                userResponse = employeeService.getUsersToLogin(userPermission.getLoginName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (userResponse == null || !userResponse.getStatus().equals(HttpCode.SUCCESS_GET)) {
            commonResponse.setMsg("登录异常！");
            commonResponse.setStatus(HttpCode.ERROR_BAD_REQUEST);
            return commonResponse;
        }
        List<Employee> users = userResponse.getData();
        if (users == null || users.isEmpty()) {
            commonResponse.setMsg("用户不存在！");
            commonResponse.setStatus(HttpCode.ERROR_BAD_REQUEST);
            return commonResponse;
        }
        for (Employee user : users) {
            if (user.getPwd().equals(pwd)) {
                commonResponse.setMsg("登陆成功！");
                commonResponse.setStatus(HttpCode.SUCCESS_GET);
                User res = new User();

                if (!redisUtil.hasKey(String.valueOf(user.getId())) ||
                        !isLogined((String) redisUtil.get(String.valueOf(user.getId())))
                        ) {
                    //未登录或已过期
                    res.setSign(createLogin(user, request));
                } else {
                    res.setSign((String) redisUtil.get(String.valueOf(user.getId())));
                }
                user.setPwd(null);
                res.setEmployee(user);
                commonResponse.setData(res);
                return commonResponse;
            }
        }
        commonResponse.setMsg("用户密码不正确！");
        commonResponse.setStatus(HttpCode.ERROR_BAD_REQUEST);
        return commonResponse;
    }

    /**
     * 根据签名判断是否已登录，登录是否有效
     *
     * @param request
     * @return
     */
    public boolean isLogined(HttpServletRequest request) {
        String sign = AuthcUtil.getSignFromRequest(request);
        return isLogined(sign);
    }

    /**
     * 根据签名判断是否已登录，登录是否有效
     *
     * @param sign
     * @return
     */
    public boolean isLogined(String sign) {
        if (Strings.isNullOrEmpty(sign))
            return false;
        return redisUtil.hasKey(sign);
    }

    /**
     * 请求时更新签名时间戳
     *
     * @param request
     */
    public void updateSginTime(HttpServletRequest request) {
        if (isLogined(request)) {
            String sign = AuthcUtil.getSignFromRequest(request);
            setUser(sign, getCurrentUser(sign));
        }
    }

    /**
     * 更新redis保存的用户信息
     *
     * @param employee
     */
    public void updateUserJson(Employee employee) {
        String sign=(String) redisUtil.get(String.valueOf(employee.getId()));
        if (isLogined(sign)) {
            Integer countTimeout = countTimeout();
            redisUtil.hset(sign, JSON, new Gson().toJson(employee), countTimeout);
        }
    }

    /**
     * redis存储信息
     *
     * @param sign
     * @param user
     */
    private void setUser(String sign, Employee user) {
        Integer countTimeout = countTimeout();
        redisUtil.hset(sign, ID, String.valueOf(user.getId()), countTimeout);
        redisUtil.hset(sign, JSON, new Gson().toJson(user), countTimeout);
        redisUtil.set(String.valueOf(user.getId()), sign, countTimeout);
    }

    @Value("${sys.login-timeout}")
    private Integer timeout;

    /**
     * 创建登录key
     *
     * @param user
     * @return
     */
    public String createLogin(Employee user, HttpServletRequest request) {
        Random random = new Random(10);//指定种子数10
        StringBuilder sign = new StringBuilder(RENT);
        sign.append(random.nextInt()).append(System.currentTimeMillis());
        String signStr = sign.toString();
        setUser(signStr, user);
        user.setLastLoginTime(new Date());
        try {
            user.setLoginIp(IPUtil.getIpAddress(request));
        } catch (IOException e) {
            e.printStackTrace();
        }
        employeeService.modify(user);
        return signStr;
    }

    /**
     * 登录退出
     *
     * @param sign
     */
    public void layout(String sign) {

        redisUtil.del(String.valueOf(getCurrentUserId(sign)));
        redisUtil.hdel(sign, ID);
    }

    /**
     * 登录退出
     *
     * @param request
     */
    public void layout(HttpServletRequest request) {
        layout(AuthcUtil.getSignFromRequest(request));
    }


    /**
     * sign获取登录用户
     *
     * @param sign
     * @return
     */
    public Long getCurrentUserId(String sign) {
        Long id = 0L;
        Object object = redisUtil.hget(sign, ID);
        try {
            id = Long.valueOf((String) object);
        } catch (Exception e) {
            try {
                id = Long.valueOf((Integer) object);
            } catch (Exception e1) {
                id = (Long) object;
            }
        }
        return id;
    }

    /**
     * sign获取登录用户
     *
     * @param sign
     * @return
     */
    public Employee getCurrentUser(String sign) {
        if(Strings.isNullOrEmpty(sign))
            return null;
        return new Gson().fromJson((String) redisUtil.hget(sign, JSON), Employee.class);
    }

    /**
     * sign获取登录用户
     *
     * @param request
     * @return
     */
    public Employee getCurrentUser(HttpServletRequest request) {
        String header = Strings.nullToEmpty(request.getHeader("id"));
        if(!header.equals("")) {
            Long id=Long.valueOf(header);
            return employeeService.getEmployeeById(id).getData();
        }
        return getCurrentUser(AuthcUtil.getSignFromRequest(request));
    }

    /**
     * 转成秒数
     *
     * @return
     */
    private Integer countTimeout() {
        return timeout * 60;
    }
}
